﻿
namespace Mulala.Cavan.Core.Extension
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Web;

    /// <summary>
    ///     Extensions available on every place of the framework.
    /// </summary>
    public static partial class Ext
    {
        #region Is()
        /// <summary>
        ///     Returns 'true' if value is NOT null.
        /// </summary>
        /// <param name = "value"></param>
        /// <returns>true if object is not null</returns>
        [Pure]
        public static bool Is(this object value)
        {
            return value != null;
        }

        [Pure]
        public static bool Is<T>(this T? value)
            where T : struct
        {
            return value.HasValue;
        }
        #endregion Is()

        #region IsNull()
        /// <summary>
        ///     if value is null 'true' is returned
        /// </summary>
        /// <param name = "value"></param>
        /// <returns>returns true if object is null</returns>
        [Pure]
        public static bool IsNull(this object value)
        {
            return value == null;
        }

        [Pure]
        public static bool IsNotNull(this object value)
        {
            return value != null;
        }

        [Pure]
        public static bool IsNull<T>(this T? value)
            where T : struct
        {
            return !value.HasValue;
        }
        #endregion IsNull()

        #region IsEmpty() IsNotEmpty() string
        /// <summary>
        ///     abbr. for (!string.IsNullOrEmpty(value)) : value.IsNotEmpty()
        /// </summary>
        /// <returns>true if not null NOR empty</returns>
        [Pure]
        public static bool IsNotEmpty(this string value)
        {
            return !value.IsEmpty();
        }

        /// <summary>
        ///     abbr. for 'string.IsNullOrEmpty(value)' : value.IsEmpty()
        /// </summary>
        /// <returns>true if null or empty</returns>
        [Pure]
        public static bool IsEmpty(this string value)
        {
            return string.IsNullOrEmpty(value);
        }
        #endregion IsEmpty() IsNotEmpty() string

        #region IsEmpty() IsNotEmpty() Enumerable
        /// <summary>
        ///     abbr. for value.Is() && value.Count() > 0;
        /// </summary>
        /// <returns>true if not null NOR empty</returns>
        [Pure]
        public static bool IsNotEmpty<T>(this IEnumerable<T> value)
        {
            return !value.IsEmpty();
        }

        /// <summary>
        ///     abbr. for 'value.IsNull() || value.Count() == 0;'
        /// </summary>
        /// <returns>true if null or empty</returns>
        [Pure]
        public static bool IsEmpty<T>(this IEnumerable<T> value)
        {
            return value.IsNull() || value.Count() == 0;
        }
        #endregion IsNotEmpty()

        #region IList<>.Append()
        public static IList<T> Append<T>(this IList<T> list, T value)
        {
            list.Add(value);
            return list;
        }
        #endregion IList<>.Append()

        public static IList<string> ToStringArray(this long num)
        {
            String convertResult = String.Empty;
            Boolean negative = false;
            if (num < 0)
            {
                negative = true;
                num = (Math.Abs(num) ^ 255) + 1;
            }
            while (true)
            {
                convertResult = convertResult.Insert(0, (num % 2).ToString());
                if (num / 2 < 2)
                {
                    convertResult = convertResult.Insert(0, (num / 2).ToString());
                    break;
                }
                num = num / 2;
            }
            convertResult = convertResult.PadLeft(15, '0');
            convertResult = convertResult.PadLeft(16, negative ? '1' : '0');
            IList<string> result = new List<string>();
            foreach (char c in convertResult.ToArray())
            {
                result.Add(c.ToString());
            }
            return result;
        }

        public static int[] ToPositionArray(this long num)
        {
            IList<string> binaries = num.ToStringArray();
            List<int> result = new List<int>();
            int index = 0;
            foreach (string c in binaries.Reverse())
            {
                if (c == "1")
                {
                    result.Add(index);
                }
                index = index + 1;
            }
            return result.ToArray();
        }

        public static IList<string> ToPosition(this long num)
        {
            IList<string> binaries = num.ToStringArray();
            List<string> result = new List<string>();
            int index = 0;
            foreach (string c in binaries.Reverse())
            {
                if (c == "1")
                {
                    result.Add(index.ToString());
                }
                index = index + 1;
            }
            return result;
        }

        public static long ToBinaryValue(this string value)
        {
            long result = 0;
            string[] positions = value.Split(',');
            foreach (string position in positions)
            {
                result = result + (long)Math.Pow(2, double.Parse(position));
            }
            return result;
        }
    }
}